<?php

class Router
{

    /**
     * @var array
     */
    protected $_routes = array();

    /**
     * process rule before match request
     * @param array
     */
    protected $_rules = array();

    /**
     * list of rule objects
     * @param array $rules
     * @return Router
     */
    public function setRules($rules)
    {
        foreach ($rules as $name => $rule)
        {
            $this -> _rules[$name] = new $rule;
        }
        return $this;
    }

    /**
     * add rule
     * @param string $name
     * @param Router_Rule_Abstract
     * @return Router
     */
    public function addRule($name, $rule)
    {
        $this -> _rules[$name] = $rule;
        return $this;
    }

    /**
     * remove rule
     * @param string $name
     * @return Router
     */
    public function removeRule($name)
    {
        if (isset($this -> _rules[$name]))
        {
            unset($this -> _rules[$name]);
        }
        return $this;
    }

    /**
     * clear all rules
     * @return Router
     */
    public function clearRule()
    {
        $this -> _rules = array();
        return $this;
    }

    /**
     * @param string $name
     * @return Router_Route_Abstract
     */
    public function getRoute($name)
    {
        if (!isset($this -> _routes[$name]))
        {
            return null;
        }

        if (!is_object($this -> _routes[$name]))
        {
            $this -> _routes[$name] = $this -> _createRoute($this -> _routes[$name]);
        }

        return $this -> _routes[$name];

    }

    /**
     * @param array $routes
     * @return Router
     */
    public function setRoutes($routes)
    {
        $this -> _routes = $routes;
        return $this;
    }

    /**
     * @param string $name
     * @param any $spec
     * @return Router
     */
    public function setRoute($name, $spec)
    {
        $this -> _routes[$name] = $spec;
        return $this;
    }

    /**
     * @var Request
     */
    public function match($request)
    {
        foreach ($this->_rules as $rule)
        {
            if ($rule -> match($request))
            {
                return 1;
            }
        }
        /**
         * check if it is match a request.
         */
        $path = $request -> getParam('path');

        foreach ($this->_routes as $name => $route)
        {
            if (!$route instanceof Router_Route_Abstract)
            {
                $this -> _routes[$name] = $route = $this -> _createRoute($route);
            }
            /**
             * @var result
             */
            if ($route -> match($request))
            {
                return 1;
            }
        }
        return 0;
    }

    /**
     * @param array $spec
     * @return Router_Route_Spec
     */
    protected function _createRoute($spec)
    {
        list($class, $params) = $spec;
        return new $class($params);
    }

}
